package com.auxgroup.smarthome.tree;

import org.apache.commons.collections.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @Author: laiqiuhua.
 * @Date: 2017/10/23 14:27.
 */
public final class TreeNodeBuilder {

    public static TreeNodeBuilder getInstance() {
        return new TreeNodeBuilder();
    }

    public List<TreeNode> buildListToTree(List<TreeNode> dirs) {
        List<TreeNode> roots = findRoots(dirs);
        List<TreeNode> notRoots = (List<TreeNode>) CollectionUtils
                .subtract(dirs, roots);
        for (TreeNode root : roots) {
            root.setChildren(findChildren(root, notRoots));
        }
        return roots;
    }

    private List<TreeNode> findRoots(List<TreeNode> allTreeNodes) {
        List<TreeNode> results = new ArrayList<TreeNode>();
        for (TreeNode TreeNode : allTreeNodes) {
            boolean isRoot = true;
            for (TreeNode comparedOne : allTreeNodes) {
                if (TreeNode.getPid().equals(comparedOne.getId())) {
                    isRoot = false;
                    break;
                }
            }
            if (isRoot) {
                TreeNode.setLevel(0);
                results.add(TreeNode);
                TreeNode.setRootId(TreeNode.getId());
            }
        }
        return results;
    }

    public List<TreeNode> findChildren(TreeNode root, List<TreeNode> allTreeNodes) {
        List<TreeNode> children = new ArrayList<TreeNode>();

        for (TreeNode comparedOne : allTreeNodes) {
            if (comparedOne.getPid().equals(root.getId())) {
                comparedOne.setParentNode(root);
                comparedOne.setLevel(root.getLevel() + 1);
                children.add(comparedOne);
            }
        }
        List<TreeNode> notChildren = (List<TreeNode>) CollectionUtils.subtract(allTreeNodes, children);
        for (TreeNode child : children) {
            List<TreeNode> tmpChildren = findChildren(child, notChildren);
            if (tmpChildren == null || tmpChildren.size() < 1) {
                child.setLeaf(true);
            } else {
                child.setLeaf(false);
            }
            child.setChildren(tmpChildren);
        }
        return children;
    }

    public List<TreeNode> findChildNode(TreeNode root, List<TreeNode> treeNodes, Set<TreeNode> resultNode) {
        List<TreeNode> children = new ArrayList<>();

        for (TreeNode node : treeNodes) {
            if (node.getPid().equals(root.getId())) {
                node.setParentNode(root);
                node.setLevel(root.getLevel() + 1);
                children.add(node);
                resultNode.add(node);
            }
        }
        List<TreeNode> notChildren = (List<TreeNode>) CollectionUtils.subtract(treeNodes, children);
        for (TreeNode child : children) {
            List<TreeNode> tmpChildren = findChildNode(child, notChildren, resultNode);
            if (tmpChildren == null || tmpChildren.size() < 1) {
                child.setLeaf(true);
            } else {
                child.setLeaf(false);
            }
            resultNode.addAll(tmpChildren);
        }
        return children;
    }

}
